<template>
    <div>
        <div ref="divRef"> Setup方法 </div>
        <!-- <div @click="addCount" style="cursor: pointer">
            当前count: {{ count }} - {{ state.count }}
        </div> -->
        <!-- <div @click="addStateCount" style="cursor: pointer">
            当前count: {{ count }} - {{ state.count }} - {{ state.name }} - {{ state.age }}
        </div>
        <div>
            {{ size || 0 }}
        </div> -->
        <!-- <div @click="changeState">
            {{ name }} - {{ age }} - {{ stateCount }}
        </div> -->
        <!-- <div>
            {{ unTestRef }}
        </div> -->
        <!-- <div>
            {{ msg }} - {{ count }}
        </div> -->
    </div>
</template>

<script lang="ts">
import { defineComponent, isProxy, isReactive, isReadonly, isRef, onMounted, reactive, readonly, ref, toRef, toRefs, unref, toRaw, markRaw } from 'vue'

export default defineComponent({
    props: {
        msg: String,
        count: Number
    },
    setup(props, ctx) {
        console.log('setup render');
        // let count = 0
        // const addCount = () => {
        //     count += 1
        //     console.log('count', count);
        // }

        // 1、ref：用来定义值类型响应式数据
        // ref的值修改需要通过.value的形式
        // ref用于模板&reactive时会自动解构value
        // ref用于获取dom元素
        // let count = ref(0)
        // // console.log(count);
        // const addCount = () => {
        //     count.value += 1
        //     // console.log('count', count.value);
        // }
        // const divRef = ref(null)
        // onMounted(() => {
        //     // console.log(divRef.value);
        // })

        // 2、reactive：用来定义对象响应式数据
        // Vue.ovserve替换api
        // reactive中的ref值始终保持引用关系
        // let count = ref(0)
        // const state = reactive({
        //     name: '张三',
        //     age: 30,
        //     count,
        //     current: 1,
        //     total: 0
        // })
        // const addStateCount = () => {
        //     state.count += 1
        //     // console.log('count', state.count);
        // }
        // // console.log(state);

        // 3、toRef从reactive副本转换具有ref引用的数据
        // 从reactive副本转换出的属性仍然与副本保持引用
        // let name = toRef(state, 'name')
        // console.log(name.value);
        // name.value = '李四'
        // console.log(state.name);

        // 即使解构的属性不存在，也会返回一个可用的ref引用，并与原reactive副本保持引用
        // let size = toRef(state, 'size')
        // console.log(size.value)
        // state.size = 10
        // console.log(size.value);

        // 4、toRefs
        // const { name, age, count: stateCount } = toRefs(state)
        // const changeState = () => {
        //     state.name = '李四'
        //     console.log(state);
        // }

        // 5、readyonly，参数对象可以是普通数据或响应式数据
        // const pageObj = readonly<any>({
        //     current: 1,
        //     total: 10,
        //     size: 20
        // })
        // pageObj.current = 2
        // console.log(pageObj.current); // 1

        // 6、isRef
        // const test = ref('test')
        // console.log('isRef', isRef(test));

        // 7、isReactive
        // const obj = reactive({})
        // console.log('isReactive', isReactive(obj));

        // 8、isReadonly
        // const ro = readonly<any>(obj)
        // console.log('isReadonly', isReadonly(ro));

        // 8、isProxy 
        // const obj = reactive({})
        // const ro = readonly<any>(obj)
        // console.log('isProxy', isProxy(obj), isProxy(ro));

        // 9、unref 从响应式ref数据中返回普通数据
        // const testRef = ref(0)
        // let unTestRef = unref(testRef)
        // console.log(unTestRef);
        // setTimeout(() => {
        //     unTestRef = 1
        //     console.log(unTestRef);
        // }, 1000);

        // 10、toRaw 从响应式reactive数据中返回普通数据
        // const rawObj = reactive({ name: '张三' })
        // let toRawObj = toRaw(rawObj)
        // console.log(toRawObj);

        // 11、markRaw 标记一个对象永远不被转换成Proxy
        // const normalObj = markRaw({ name: '张三' })
        // const reactiveObj = reactive(normalObj)
        // console.log(normalObj, reactiveObj);

        // 剩余Api自行研究学习

        // props, ctx
        console.log(props, ctx);
        // props
        // props参数必须在props选项中预定义，否则无法获取
        // props是响应式的，不能直接对其进行解构
        // const { msg, count } = toRefs(props)

        // ctx: attrs / slots / emit
        // ctx是非响应式的，所以可以安全的对其进行解构
        // this.$emit() -> emit()

        // 返回结果暴露给template使用
        return {
            // count,
            // addCount,
            // addStateCount,
            // divRef,
            // state,
            // size,
            // name,
            // age,
            // stateCount,
            // changeState,
            // unTestRef,
            // msg,
            // count
        }
    },
})
</script>
